#include <bits/stdc++.h>
using namespace std;

//详细使用查看lambda.md文档
//专门对捕获列表是因为其容易出错
//其他的使用和函数十分类似

void Test_Capture_list1()
{
    //以下是最简单的lambda表达式，但是一般没什么用处
    []{};

    //一般lambda表达式用来处理较小简单的函数，类型直接用auto判断保存会比较容易
    auto f1 = [](int x,int y){return x+y;};
    int a = 0;
    //这里就可以表现[]自动捕捉上下文参数的特点,=就是以值传递，捕获上下文所有,因为默认是常性的，需要加个mutable
    auto f2 = [=]()mutable{return a+=4;};
    cout<<f2()<<endl;

    //就是以引用传递，捕获上下文所有,会改变变量的值,可以查看调试查看值得变化
    auto f3 = [&]{return a+=4;};
    cout<<f3()<<endl;

    auto f4 = [a]()mutable{return a+=4;};
    cout<<f4()<<endl;

    auto f5 = [&a]{return a+=4;};
    cout<<f5()<<endl;
    
    return ;
}

//全局变量
int z = 0;
void Test_Capture_list2()
{

    struct  A
    {
        A()
        {
            static int b= 100;

            //值传递捕捉this指针
            // auto f1 = [this](){return *this;};
            
            //auto f2 = [&this](){return this;};//C++不支持this指针得引用传递
            auto f2 = [this](){return this;};
            //auto f3 = [a](){return };//lambda表达式只允许捕获当前作用域的局部变量

            //理论上，lambda是不允许捕获全局或者静态变量的，
            //但是Gcc只是报警告
            //实际运行结果，无论是何种捕获（引用或者传值）其实就相当于没有捕获直接使用该全局或者静态变量一样
            //这里是值得注意的，尤其是你以为是传值，实际就是用的本身，很容易导致坑
            // auto f4 = [b](){return b++;};
            // f4();
            // auto f5 = [&z](){z++;};
            // f5();
            int c = b;
        }
        int a = 0;
    };
    A();
}

void Test_Capture_list3()
{
    int a=0;
    //这里从理论上是不被允许的，然而gcc编译器报的依旧只是报个警告
    auto f1 = [=]()mutable->int{return a++;};
    f1();
    cout<<"a:>>"<<a<<endl;
}

